﻿#include <iostream>

// DoAttack是攻击者的想要执行的代码
// 这里为了演示方便，直接一起编译了
// 实际上攻击者可以将此函数先转成机器码，再通过应用程序的对外接口放到buffer中传进来。
void DoAttack()
{
    std::cout << "Do attack!\n";
    exit(0);
}

// 正常业务代码，处理外部输入
void DoSomething(char* buffer, int len)
{
    char dstBuffer[12] = {0};
    // 调用memcpy，没有校验len的大小是否小于12。
    // 实际len是20，比dsBuffer多了8个字节。
    // 多的8个字节中，后面那4个字节（即: buffer+16），就是DoAttack的函数地址,写到了dstBuffer+16处。
    memcpy(dstBuffer, buffer, len);

    // 这里只是为了演示，简单打印一些内容。
    std::cout << "Do something!\n";
}

// debug版本，需要设置工程属性：
// 1. c/c++->代码生成->基本运行时检查，选“默认值”，即关闭。
// 2. 链接器->增量链接，选“否”。
int main()
{
    // buffer可以是通过gets或者restful等从外部获取的不可信数据
    // 这里为了演示方便，直接在代码里写死。
    char buffer[20] = {0};

    // 最后4个字节放的DoAttack函数的首地址
    *(int32_t*)(buffer + 16) = (int32_t)DoAttack;

    // 将特殊构造的buffer传给业务函数
    DoSomething(buffer, sizeof(buffer));
    std::cout << "main end!\n";
}